#    This is part of WeatherFront.
#
#    Copyright (C) 2010 Stefan Sieber
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; version 2 of the License.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with this program; if not, write to the Free Software Foundation, Inc.,
#    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#


import re
import string


verbose=1
def log(s,level=1):
	if verbose >= level:
		Foundation.NSLog( u"%s: WeatherAPI: %@", "WeatherFrontLog", s ) 
	pass
	
	
"""
	Thanks to Fredrik Lundh (http://effbot.org). The XML parser sample on his website is the foundation for the XMLscanner class.
"""
class XMLscanner:
	
	def __init__(self):
		self.xml_stream = []
		# xml tokenizer pattern
		self.regex = re.compile("<([/?!]?\w+)|&(#?\w+);|([^<>&'\"=\s]+)|(\s+)|(.)")
		self.xml_entities = {"amp": "&", "apos": "'", "gt": ">", "lt": "<", "quot": '"'}

	def xml(self, attrib):
		#log("XML %s" % attrib)
		#self.xml_stream[XML] = attrib
		return
		
	def start(self, tag):
		#log("START %s" % tag)
		value = {}
		value[tag] = "START"
		self.xml_stream.append(value)
		return
		
	def end(self, tag):
		#log("END %s" % tag)
		value = {}
		value[tag] = "END"
		self.xml_stream.append(value)
		return
		
	def data(self, text):
		#log("DATA %s" % text)
		value = {}
		value["DATA"] = text
		self.xml_stream.append(value)
		return
		
	def scan(self, str):
		# split string into xml elements

		# create a scanner function for this string
		def gettoken(space=0, scan=self.regex.scanner(str).match):
			# scanner function (bound to the string)
			try:
				while 1:
					m = scan()
					code = m.lastindex
					text = m.group(m.lastindex)
					if not space or code != 4:
						return code, text
			except AttributeError:
				raise EOFError

		# token categories
		TAG = 1; ENTITY = 2; STRING = 3; WHITESPACE = 4; SEPARATOR = 5

		start = self.start; end = self.end; data = self.data;
		
		try:
			while 1:
				code, text = gettoken();
				if code == TAG:
					# deal with tags
					type = text[:1]
					if type == "/":
						# end tag
						end(text[1:])
						code, text = gettoken(1)
						if text != ">":
							raise SyntaxError, "malformed end tag"
					elif type == "!":
						# document type declaration (incomplete)
						value = []
						while 1:
							# parse start tag contents
							code, text = gettoken(1)
							if text == ">":
								break
							value.append(text)
						value = string.join(value, "")
					else:
						# start tag or procesing instruction
						tag = text
						attrib = {}
						while 1:
							# parse start tag contents
							code, text = gettoken(1);
							if text == ">":
								start(tag)
								if attrib != {}:
									data(attrib)
								break
							if text == "/":
								start(tag)
								data(attrib)
								end(tag)
								data(attrib)
								break
							if text == "?":
								if type != text:
									raise SyntaxError, "unexpected quotation mark"
								code, text = gettoken(1)
								if text != ">":
									raise SyntaxError, "expected end tag"
								try:
									self.xml(attrib)
								except AttributeError:
									pass
								break
							if code == STRING:
								# tag attribute
								key = text
								code, text = gettoken(1)
								if text != "=":
									raise SyntaxError, "expected equal sign"
								code, quote = gettoken(1)
								if quote != "'" and quote != '"':
									raise SyntaxError, "expected quote"
								value = []
								while 1:
									code, text = gettoken()
									if text == quote:
										break
									if code == ENTITY:
										try:
											text = self.fixentity(text)
										except ValueError:
											text = self.fixentity(text)
									value.append(text), "append attribute"
								attrib[key] = string.join(value, "")
				elif code == ENTITY:
					# text entities
					try:
						text = self.fixentity(text)
					except ValueError:
						text = self.fixentity(text)
					data(text)
				elif code == WHITESPACE:
					# whitespace
					pass
				else:
					# tag content <x>CONTENT</x>
					data(text)
		except EOFError:
			pass
		except SyntaxError, v:
			# generate nicer error message
			raise

	

	def fixentity(self, entity):
		#log('Error in XMLParser: %s' % entity)
		# map entity name to built-in entity
		##try:
		##	return self.xml_entities[entity]
		##except KeyError:
		##	pass
		# assume numeric entity (raises ValueError if malformed)
		##if entity[:2] == "#x":
		##	value = int(entity[2:], 16)
		##else:
		##	value = int(entity[1:])
		##if value > 127:
		##	return unichr(value)
		##return chr(value)
		return 'error'
		
		
	""" Returns the content of a given tag in a stream as SEQUENCE like mySubSet=[]
		The value of the sequence will be an amount of DICTIONARYs like myDict={'DATA': 'Dortmund'} 
		
		Sample
		tmp = self.getSubSet(currentConditions[0], 't') // tag = 't' like for text
		occurence: 4 
		print tmp	 >> [[{'DATA': 'Partly'}, {'DATA': 'Cloudy'}], [{'DATA': 'W'}], [{'DATA': 'Low'}], [{'DATA': 'First'}, {'DATA': 'Quarter'}]] 
		print tmp[2] >> [{'DATA': 'Low'}]
	"""
	def getSubSet(self, stream, tag):
		occurCounter=0
		i=0
		startPos=[]
		endPos=[]
		#print i, startPos, endPos, tag
		#print "***\n", stream, "***\n"
		for item in stream:
			i+=1
			if item.has_key(tag):
				if item.get(tag) == 'START':
					occurCounter += 1
					startPos.append(i)
				if item.get(tag) == 'END':
					endPos.append(i-1)
		#print occurCounter, startPos, endPos
		i=0
		returnValue=[]
		while i < occurCounter:
			returnValue.append(stream.__getslice__(startPos[i],endPos[i]))
			i+=1;
		return returnValue

